<?php

namespace app\admin\controller;

use think\captcha\facade\Captcha;
use think\facade\Log; // 引入 Log 类
use app\service\Encryptor;
use app\service\CZDB;
use app\service\JwtSerice as JwtSerice;

use app\common\AdminController;
use app\admin\model\User as UserDB;
use app\admin\validate\User as UserValidate;
use Ramsey\Uuid\Uuid as Uuid;

class User extends AdminController
{

    private const EXP = 60 * 60; // 设置过期时间为一小时
    protected function initialize()
    {

        $this->model = new UserDB();

    }
    public function test()
    {
        // phpinfo();
        // $res = CZDB::getAddressByIP("113.120.48.45");
        return phpinfo();
    }
    public function login()
    {
        $datas = input("post.");
        try {
            Validate(UserValidate::class)->scene('login')->check($datas);
        } catch (\Throwable $th) {
            // throw $th;
            return error($th->getMessage());
        }
        $user = UserDB::where('user_name', $datas['username'])->find();
        if ($user && $user->status == 1) {
            $password = Encryptor::decrypt($datas['password']);
            // $hash = password_hash($password,PASSWORD_BCRYPT);
            if (password_verify($password, $user->user_password)) {
                $uuid = UUid::uuid4();
                $token = JwtSerice::setToken($user->id, $uuid);
                $this->updateLogin($user);
                Log::channel('sys')->record([
                    'content' => "用户登录--$user->nickname",
                    'create_by' => $datas['username'],
                    'log_type' => '1',
                    'ipaddress' => request()->header('x-real-ip')
                ]);
                return success("登录成功", ['token' => $token]);
            } else {
                return error("登录失败，密码或用户名错误");
            }
        } else {
            return error("登录失败，用户不存在或状态异常");
        }
    }

    public function userInfo()
    {
        try {
            $uid = $this->userId;
            $userToken = $this->userToken;
            // $jwtToken = JwtSerice::setToken($uid, $userToken);
            $infoStatus = $this->uRedis->exists("info:$uid");
            $roleStatus = $this->uRedis->exists("role:$uid");
            if ($infoStatus && $roleStatus) {
                $res = $this->redisGetUser($uid);
            } else {
                $res = $this->sqlGetUser($uid);
            }
            $this->userInfo = $res;
            return success('获取成功', $res);
        } catch (\Throwable $th) {
            // return error("获取用户信息失败", 500);
            return error($th->getMessage(), 500);
        }
    }
    private function sqlGetUser($uid)
    {

        $user = UserDB::where('id', $uid)->with([
            'role' => function ($query) {
                $query->where('status', '=', '1');
            }
        ])->find();
        if ($user) {
            $rolesKey = $user->role->column('roleKey');
            $rolesId = $user->role->column('id');
            $roles = $user->role->toArray();
            $roleData = array_column($roles, 'id', 'roleKey');
            $permissions = $this->getRolePerms($rolesId);
            $res = [
                'permissions' => $permissions,
                'user' => [
                    'uid' => $user->user_id,
                    'username' => $user->user_name,
                    'nickname' => $user->nickname,
                    'avatar' => $user->avatar,
                    'phone' => $user->phone_number,
                    'sex' => $user->sex,
                    'loginIp' => $user->login_ip,
                    'loginAddress' => $user->login_address,
                    'role' => $rolesKey,
                    'loginTime' => $user->login_time,
                    'createTime' => $user->create_time
                ]
            ];
            $this->uRedis->hSet("info:$uid", $res['user']);
            $this->uRedis->hSet("role:$uid", $roleData);
            $this->uRedis->expire("info:$uid", self::EXP);
            $this->uRedis->expire("role:$uid", self::EXP);
            return $res;
        }
        return error('登录失败，未找到用户', 401);
    }

    private function redisGetUser($uid)
    {
        $user = $this->uRedis->hGetAll("info:$uid");
        $role = $this->uRedis->hGetAll("role:$uid");
        $rolesKey = array_keys($role);
        $rolesId = array_values($role);
        $permissions = $this->getRolePerms($rolesId);
        $user['role'] = $rolesKey;
        $res = [
            'permissions' => $permissions,
            'user' => $user
        ];
        return $res;
    }
    private function getRolePerms($rolesId)
    {
        $perms = [];
        if (!in_array($this->adminRoleId, $rolesId)) {
            foreach ($rolesId as $role) {
                $perms[] = 'perms:roleId:' . $role;
            }
            $res = $this->pRedis->sUnion($perms);
            return $res;
        }
        return ['*:*:*'];
    }

    /**
     * Summary of getRouters
     * 获取路由
     */
    public function getRouters()
    {
        try {
            $uid = $this->userId;
            $role = $this->uRedis->hGetAll('role:' . $uid);
            $rolesId = array_values($role);
            $menuCurrent = [];
            if (in_array($this->adminRoleId, $rolesId)) {
                $menuDb = \app\admin\model\Menu::where([
                    ['menu_type', '<>', '3'],
                    ['status', '=', '1']
                ])->select();
                foreach ($menuDb as $menu) {
                    $menuCurrent[$menu->id] = $this->setMenu($menu);
                }
            } else {
                $roles = \app\admin\model\Role::where([['id', 'in', $rolesId], ['status', '=', '1']])
                    ->with([
                        'menu' => function ($query) {
                            $query->where([
                                ['menu_type', '<>', '3'],
                                ['status', '=', '1']
                            ]);
                        }
                    ])->select();
                foreach ($roles as $role) {
                    foreach ($role->menu as $menu) {
                        $menuCurrent[$menu->id] = $this->setMenu($menu);
                    }
                }
            }
            $menuCurrent = array_values($menuCurrent);
             array_multisort(array_column($menuCurrent, 'orderNum'), SORT_DESC, $menuCurrent);

            $menu = buildTree($menuCurrent);
            return success("获取成功", $menu);
        } catch (\Throwable $th) {
            //throw $th;
            return error($th->getMessage(), 500);
        }
    }

    private function setMenu($menu)
    {
        $menuType = $menu->menuType;
        $menuItem = [
            "id" => $menu->id,
            "pid" => $menu->pid,
            "name" => ucfirst($menu->path),
            "orderNum" => $menu->orderNum,
            "path" => $menu->pid == "0" ? "/" . $menu->path : $menu->path,
            "hidden" => $menu->visible ? true : false,
            "redirect" => $menuType == "1" ? "noRedirect" : "",
            "component" => $menuType == "1" ? "Layout" : $menu->component,
            "meta" => [
                "title" => $menu->menuName,
                "icon" => $menu->icon,
                "cache" => $menu->isCache == '1' ? true : false,
                "link" => $menu->isFrame == '1' ? $menu->component : null
            ],
        ];
        if ($menu->menuType == "2" && $menu->pid == '0') {
            $menuItem = [
                "id" => $menu->id,
                "pid" => $menu->pid,
                "path" => "/",
                "hidden" => false,
                "component" => "Layout",
                "orderNum" => $menu->orderNum,
                "children" => [$menuItem]
            ];
        }
        return $menuItem;
    }

    protected function updateLogin($user)
    {
        $ip = request()->header('x-real-ip');
        // $ip  = '113.120.48.45';
        $user->login_address = CZDB::getAddressByIP($ip);
        $user->login_ip = $ip;
        $user->login_time = time();
        $user->save();
    }

    public function captcha()
    {

        // return Captcha::create();

        $code = Captcha::create();
        return success("获取成功", ['img' => $code['img']]);
    }

    public function logout()
    {
        $authAuthorization = request()->header('Authorization');
        if (!$authAuthorization || strpos($authAuthorization, 'Bearer ') != 0) {
            return success("退出成功", null);
        }

        $token = str_replace('Bearer ', '', $authAuthorization);
        $info = JwtSerice::validateToken($token);
        $id = $info['uid'];
        $user = $this->model->find($id);

        $rToken = $this->uRedis->get("token:" . $info['uid']);
        if ($info['token'] == $rToken) {
            Log::channel('sys')->record([
                'content' => "用户退出登录--" . $user->nickname,
                'create_by' => $user->user_name,
                'log_type' => '2',
                'ipaddress' => request()->header('x-real-ip')
            ]);
            $this->uRedis->del("info:" . $info['uid']);
            $this->uRedis->del("role:" . $info['uid']);
            JwtSerice::delToken($info['uid']);
        } else {
            Log::channel('sys')->record([
                'content' => "用户token失效，退出登录--" . $user->nickname,
                'create_by' => $user->user_name,
                'log_type' => '2',
                'ipaddress' => request()->header('x-real-ip')
            ]);
        }

        return success("退出成功", null);
    }
}
